package com.black.knight.chess.model;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;

import com.black.knight.chess.R;
import com.black.knight.chess.domain.PNGGame.PNGGames;
import com.black.knight.chess.domain.PNGOpening.PNGOpenings;
import com.black.knight.chess.domain.PNGProblem.PNGProblems;
import com.codethesis.pgnparse.PGNGame;
import com.codethesis.pgnparse.PGNSource;

public class PNGGamesModel {
	
	private static PNGGamesModel model;
	
	private PGNGame currentGame;
	
	public static ExecutorService executor = Executors.newCachedThreadPool();
	
	private int selectedCategory = 0;
	
	private String lastSearch = "";
	
	private Map<String, String> tags;
	
	public PNGGamesModel() {
		try {
			Cursor cursorProblems = getOpeningsCursor();
			if(cursorProblems.getCount() == 0) {
				cursorProblems.close();
				executor.execute(new Runnable() {
					@Override
					public void run() {
						try {
							importProblems();
						} catch (SQLException e) {
						}
					}
				});
			}
			
			Cursor cursor = getOpeningsCursor();
			
			if(cursor.getCount() == 0) {
				cursor.close();
				executor.execute(new Runnable() {
					@Override
					public void run() {
						Thread t = Thread.currentThread();
		                t.setPriority(Thread.MIN_PRIORITY);  
						
						importOpenings();
					}
				});
			}
		} catch (Exception e) { }
	}
	
	private void importProblems() {
		ContentValues values = new ContentValues();
		values.put(PNGProblems.DESCRIPTION, "Level 1 - Game 1");
		values.put(PNGProblems.FEN, "r1bqkbnr/ppppp2p/2n3p1/7Q/8/2NBP3/PPPP1PPP/R1B1K1NR w KQkq - 0 0");
		values.put(PNGProblems.MATE_IN, 2);
		
		SahModel.context.getContentResolver().insert(PNGProblems.CONTENT_URI, values);
		
		values = new ContentValues();
		values.put(PNGProblems.DESCRIPTION, "Level 1 - Game 2");
		values.put(PNGProblems.FEN, "3R4/1q4pk/2b1p3/pn2P1P1/1p6/2p1B3/PPP5/2K3R1 w KQkq - 0 0");
		values.put(PNGProblems.MATE_IN, 1);
		
		SahModel.context.getContentResolver().insert(PNGProblems.CONTENT_URI, values);
		
		values = new ContentValues();
		values.put(PNGProblems.DESCRIPTION, "Level 2 - Game 1");
		values.put(PNGProblems.FEN, "8/p3ppp1/k1K5/p6N/P7/8/8/8 w KQkq - 0 0");
		values.put(PNGProblems.MATE_IN, 3);
		
		SahModel.context.getContentResolver().insert(PNGProblems.CONTENT_URI, values);
		
		values = new ContentValues();
		values.put(PNGProblems.DESCRIPTION, "Level 2 - Game 2");
		values.put(PNGProblems.FEN, "q6r/k3p3/4Np1r/7P/2N1Q3/2P2Pnp/4R1p1/4K3 w KQkq - 0 0");
		values.put(PNGProblems.MATE_IN, 2);
		
		SahModel.context.getContentResolver().insert(PNGProblems.CONTENT_URI, values);
		
		values = new ContentValues();
		values.put(PNGProblems.DESCRIPTION, "Level 3 - Game 1");
		values.put(PNGProblems.FEN, "8/6p1/3p4/1K1k4/p4pN1/3P4/2B5/4R3 w KQkq - 0 0");
		values.put(PNGProblems.MATE_IN, 2);
		
		SahModel.context.getContentResolver().insert(PNGProblems.CONTENT_URI, values);
		
		values = new ContentValues();
		values.put(PNGProblems.DESCRIPTION, "Level 3 - Game 2");
		values.put(PNGProblems.FEN, "r4k1r/ppp3pp/8/3R1PBQ/b1B5/2bK4/Pq4PP/6NR w KQkq - 0 0");
		values.put(PNGProblems.MATE_IN, 2);
		
		SahModel.context.getContentResolver().insert(PNGProblems.CONTENT_URI, values);
		
		values = new ContentValues();
		values.put(PNGProblems.DESCRIPTION, "Level 4 - Game 1");
		values.put(PNGProblems.FEN, "7K/8/4B3/Q6p/7k/3r2p1/6n1/6N1 w KQkq - 0 0");
		values.put(PNGProblems.MATE_IN, 2);
		
		SahModel.context.getContentResolver().insert(PNGProblems.CONTENT_URI, values);
		
		values = new ContentValues();
		values.put(PNGProblems.DESCRIPTION, "Level 4 - Game 2");
		values.put(PNGProblems.FEN, "5b2/8/1P2RnB1/1K1k4/2pN4/2P5/5n2/8 w KQkq - 0 0");
		values.put(PNGProblems.MATE_IN, 3);
		
		SahModel.context.getContentResolver().insert(PNGProblems.CONTENT_URI, values);
		
		values = new ContentValues();
		values.put(PNGProblems.DESCRIPTION, "Level 5 - Game 1");
		values.put(PNGProblems.FEN, "2R5/8/3k4/3N2p1/4K1Q1/8/8/8 w KQkq - 0 0");
		values.put(PNGProblems.MATE_IN, 2);
		
		SahModel.context.getContentResolver().insert(PNGProblems.CONTENT_URI, values);
		
		values = new ContentValues();
		values.put(PNGProblems.DESCRIPTION, "Level 5 - Game 2");
		values.put(PNGProblems.FEN, "8/2R5/1K1k2N1/2p1q3/2P1pP2/1P2B3/8/8 w KQkq - 0 0");
		values.put(PNGProblems.MATE_IN, 3);
		
		SahModel.context.getContentResolver().insert(PNGProblems.CONTENT_URI, values);
	}

	private void importOpenings() {
		InputStream is = SahModel.context.getResources().openRawResource(R.raw.openings);
		
		final StringBuffer message = new StringBuffer("");
		
		try {
			PGNSource source = new PGNSource(is);
			Iterator<PGNGame> i = source.listGames().iterator();
			
			ArrayList<ContentValues> list = new ArrayList<ContentValues>();
			
			while (i.hasNext()) {
				PGNGame game = i.next();
				
				Iterator<String> tagsIterator = game.getTagKeysIterator();
				
				String description = "";
				while (tagsIterator.hasNext()) {
					String key = tagsIterator.next();
					description += key + ": " + game.getTag(key);
					if(tagsIterator.hasNext()) description += ",\n";
				}
				
				ContentValues values = new ContentValues();
				values.put(PNGOpenings.DESCRIPTION, description);
				values.put(PNGOpenings.PNG, game.toString());
				list.add(values);
			}
			
			SahModel.context.getContentResolver().bulkInsert(PNGOpenings.CONTENT_URI, list.toArray(new ContentValues[list.size()]));
		} catch (Exception e) {
			message.append("Error while inserting PGN games!");
		}
	}
	
	private static void importGames() {
		InputStream is = SahModel.context.getResources().openRawResource(R.raw.middleg);
		
		try {
			PGNSource source = new PGNSource(is);
			Iterator<PGNGame> i = source.listGames().iterator();
			
			ArrayList<ContentValues> list = new ArrayList<ContentValues>();
			
			while (i.hasNext()) {
				PGNGame game = i.next();
				
				Iterator<String> tagsIterator = game.getTagKeysIterator();
				
				String description = "";
				while (tagsIterator.hasNext()) {
					String key = tagsIterator.next();
					description += key + ": " + game.getTag(key);
					if(tagsIterator.hasNext()) description += ",\n";
				}
				
				ContentValues values = new ContentValues();
				values.put(PNGGames.DESCRIPTION, description);
				values.put(PNGGames.PNG, game.toString());
				values.put(PNGGames.CATEGORY, "games_collection");
				list.add(values);
			}
			
			SahModel.context.getContentResolver().bulkInsert(PNGGames.CONTENT_URI, list.toArray(new ContentValues[list.size()]));
		} catch (Exception e) {
		}
	}
	
	public static PNGGamesModel getInstance() {
		if(model == null) {
			model = new PNGGamesModel();
		}
		return model;
	}

	public static boolean deleteGame(int id) {
		SahModel.context.getContentResolver().delete(PNGGames.CONTENT_URI, PNGGames.PNG_GAME_ID + " = '" + id + "'", null);
		return true;
	}
	
	public static Cursor getGamesCursor(String where) {
		return SahModel.context.getContentResolver().query(PNGGames.CONTENT_URI, new String[] {PNGOpenings.DESCRIPTION, PNGOpenings.PNG, PNGGames.FEN, PNGOpenings.PNG_GAME_ID}, where, null, null);
	}
	
	public static Cursor getOpeningsCursor() {
		return SahModel.context.getContentResolver().query(PNGOpenings.CONTENT_URI, new String[] {PNGOpenings.DESCRIPTION, PNGOpenings.PNG, PNGGames.FEN, PNGOpenings.PNG_GAME_ID}, null, null, null);
	}
	
	public static Cursor getProblemsCursor() {
		return SahModel.context.getContentResolver().query(PNGProblems.CONTENT_URI, new String[] {PNGProblems.DESCRIPTION, PNGProblems.PNG, PNGProblems.FEN, PNGProblems.MATE_IN, PNGProblems.PNG_PROBLEM_ID}, null, null, null);
	}
	
	public static Cursor getGamesLike(String where, String category) {
		if("openings".equals(category)) return getOpeningsWhere(where);
				
		if("games_collection".equals(category)) {
			Cursor cursorGames = getGamesCursor(PNGGames.CATEGORY + " = '" + category + "'");
			
			if(cursorGames.getCount() == 0) {
				cursorGames.close();
				importGames();
			}
		}
		
		return SahModel.context.getContentResolver().query(PNGGames.CONTENT_URI, new String[] {PNGGames.DESCRIPTION, PNGGames.PNG, PNGGames.FEN, PNGGames.PNG_GAME_ID}, PNGGames.CATEGORY + " = '" + category + "' AND " + where, null, null);
	}
	
	public static Cursor getProblemsLike(String where) {						
		return SahModel.context.getContentResolver().query(PNGProblems.CONTENT_URI, new String[] {PNGProblems.DESCRIPTION, PNGProblems.MATE_IN, PNGProblems.PNG, PNGProblems.FEN, PNGProblems.PNG_PROBLEM_ID}, where, null, null);
	}
	
	public static Cursor getOpeningsWhere(String where) {
		return SahModel.context.getContentResolver().query(PNGOpenings.CONTENT_URI, new String[] {PNGOpenings.DESCRIPTION, PNGOpenings.PNG, PNGGames.FEN, PNGOpenings.PNG_GAME_ID}, where, null, null);
	}

	public PGNGame getCurrentGame() {
		return currentGame;
	}

	public void setCurrentGame(PGNGame currentGame) {
		this.currentGame = currentGame;
	}

	public String getLastSearch() {
		return lastSearch;
	}

	public void setLastSearch(String lastSearch) {
		this.lastSearch = lastSearch;
	}

	public int getSelectedCategory() {
		return selectedCategory;
	}

	public void setSelectedCategory(int selectedCategory) {
		this.selectedCategory = selectedCategory;
	}

	public Map<String, String> getTags() {
		return tags;
	}

	public void setTags(Map<String, String> tags) {
		this.tags = tags;
	}
}
